import { Singleton } from "../../utils/Singleton";
import { HttpRequestConfig, HttpMethod, HttpResponseType, RequestInterceptor, ResponseInterceptor, HttpResponse, HttpErrorResponse } from "./BaseTypes";

/**
 * HTTP请求管理器
 * 基于XMLHttpRequest实现，支持拦截器、重试、超时等功能
 */
export class HttpMgr extends Singleton {

    /** 默认配置 */
    private _defaultConfig: Partial<HttpRequestConfig> = {
        method: HttpMethod.GET,
        timeout: 10000,
        responseType: HttpResponseType.JSON,
        showLoading: false,
        retryCount: 0,
        retryDelay: 1000,
        headers: {
            'Content-Type': 'application/json'
        }
    };

    /** 请求拦截器 */
    private _requestInterceptors: RequestInterceptor[] = [];
    
    /** 响应拦截器 */
    private _responseInterceptors: ResponseInterceptor[] = [];

    /** 当前请求数量（用于loading管理） */
    private _pendingRequests: number = 0;

    /** 活跃的请求映射（用于取消请求） */
    private _activeRequests: Map<string, XMLHttpRequest> = new Map();

    /**
     * 设置默认配置
     */
    public setDefaultConfig(config: Partial<HttpRequestConfig>): void {
        this._defaultConfig = { ...this._defaultConfig, ...config };
    }

    /**
     * 添加请求拦截器
     */
    public addRequestInterceptor(interceptor: RequestInterceptor): void {
        this._requestInterceptors.push(interceptor);
    }

    /**
     * 添加响应拦截器
     */
    public addResponseInterceptor(interceptor: ResponseInterceptor): void {
        this._responseInterceptors.push(interceptor);
    }

    /**
     * GET请求
     */
    public async get<T = any>(url: string, params?: any, config?: Partial<HttpRequestConfig>): Promise<HttpResponse<T>> {
        const requestConfig: HttpRequestConfig = {
            ...this._defaultConfig,
            ...config,
            url: this._buildUrl(url, params),
            method: HttpMethod.GET
        };
        return this.request<T>(requestConfig);
    }

    /**
     * POST请求
     */
    public async post<T = any>(url: string, data?: any, config?: Partial<HttpRequestConfig>): Promise<HttpResponse<T>> {
        const requestConfig: HttpRequestConfig = {
            ...this._defaultConfig,
            ...config,
            url,
            method: HttpMethod.POST,
            data
        };
        return this.request<T>(requestConfig);
    }

    /**
     * PUT请求
     */
    public async put<T = any>(url: string, data?: any, config?: Partial<HttpRequestConfig>): Promise<HttpResponse<T>> {
        const requestConfig: HttpRequestConfig = {
            ...this._defaultConfig,
            ...config,
            url,
            method: HttpMethod.PUT,
            data
        };
        return this.request<T>(requestConfig);
    }

    /**
     * DELETE请求
     */
    public async delete<T = any>(url: string, config?: Partial<HttpRequestConfig>): Promise<HttpResponse<T>> {
        const requestConfig: HttpRequestConfig = {
            ...this._defaultConfig,
            ...config,
            url,
            method: HttpMethod.DELETE
        };
        return this.request<T>(requestConfig);
    }

    /**
     * 通用请求方法
     */
    public async request<T = any>(config: HttpRequestConfig): Promise<HttpResponse<T>> {
        // 应用请求拦截器
        let processedConfig = await this._applyRequestInterceptors(config);
        
        // 显示loading
        if (processedConfig.showLoading) {
            this._showLoading();
        }

        try {
            const response = await this._executeRequestWithRetry<T>(processedConfig);
            // 应用响应拦截器
            return await this._applyResponseInterceptors(response);
        } catch (error) {
            // 处理错误
            throw await this._handleError(error, processedConfig);
        } finally {
            // 隐藏loading
            if (processedConfig.showLoading) {
                this._hideLoading();
            }
        }
    }

    /**
     * 取消指定URL的请求
     */
    public cancelRequest(url: string): void {
        const xhr = this._activeRequests.get(url);
        if (xhr) {
            xhr.abort();
            this._activeRequests.delete(url);
        }
    }

    /**
     * 取消所有活跃请求
     */
    public cancelAllRequests(): void {
        this._activeRequests.forEach((xhr, url) => {
            xhr.abort();
        });
        this._activeRequests.clear();
    }

    /**
     * 带重试机制的请求执行
     */
    private async _executeRequestWithRetry<T>(config: HttpRequestConfig): Promise<HttpResponse<T>> {
        let lastError: any;
        const maxRetries = config.retryCount || 0;

        for (let attempt = 0; attempt <= maxRetries; attempt++) {
            try {
                return await this._executeRequest<T>(config);
            } catch (error) {
                lastError = error;
                
                // 如果是最后一次尝试，直接抛出错误
                if (attempt === maxRetries) {
                    throw error;
                }

                // 等待后重试
                console.warn(`请求失败，${config.retryDelay}ms后进行第${attempt + 1}次重试`, error);
                await this._delay(config.retryDelay || 1000);
            }
        }

        throw lastError;
    }

    /**
     * 执行HTTP请求
     */
    private async _executeRequest<T>(config: HttpRequestConfig): Promise<HttpResponse<T>> {
        return new Promise<HttpResponse<T>>((resolve, reject) => {
            const xhr = new XMLHttpRequest();
            
            // 将请求添加到活跃请求映射中
            this._activeRequests.set(config.url, xhr);
            
            // 设置请求方法和URL
            xhr.open(config.method, config.url, true);
            
            // 设置响应类型
            if (config.responseType && config.responseType !== HttpResponseType.JSON) {
                xhr.responseType = config.responseType as any;
            }
            
            // 设置请求头
            if (config.headers) {
                Object.keys(config.headers).forEach(key => {
                    xhr.setRequestHeader(key, config.headers[key]);
                });
            }
            
            // 设置超时
            if (config.timeout) {
                xhr.timeout = config.timeout;
            }

            // 清理函数
            const cleanup = () => {
                this._activeRequests.delete(config.url);
            };

            // 成功回调
            xhr.onload = () => {
                cleanup();
                
                if (xhr.status >= 200 && xhr.status < 300) {
                    let responseData: T;
                    
                    try {
                        // 根据响应类型解析数据
                        switch (config.responseType) {
                            case HttpResponseType.JSON:
                                responseData = xhr.responseText ? JSON.parse(xhr.responseText) : null;
                                break;
                            case HttpResponseType.TEXT:
                                responseData = xhr.responseText as any;
                                break;
                            default:
                                responseData = xhr.response;
                        }
                    } catch (e) {
                        reject(this._createError('响应数据解析失败', config, xhr.status, e));
                        return;
                    }

                    const response: HttpResponse<T> = {
                        data: responseData,
                        status: xhr.status,
                        statusText: xhr.statusText,
                        headers: this._parseHeaders(xhr.getAllResponseHeaders()),
                        config
                    };
                    
                    resolve(response);
                } else {
                    reject(this._createError(`HTTP错误: ${xhr.status} ${xhr.statusText}`, config, xhr.status));
                }
            };

            // 错误回调
            xhr.onerror = () => {
                cleanup();
                reject(this._createError('网络错误', config));
            };

            // 超时回调
            xhr.ontimeout = () => {
                cleanup();
                reject(this._createError(`请求超时(${config.timeout}ms)`, config));
            };

            // 请求被取消
            xhr.onabort = () => {
                cleanup();
                reject(this._createError('请求被取消', config));
            };

            // 发送请求
            try {
                const requestData = this._prepareRequestData(config);
                xhr.send(requestData);
            } catch (e) {
                cleanup();
                reject(this._createError('发送请求失败', config, undefined, e));
            }
        });
    }

    /**
     * 延迟函数
     */
    private _delay(ms: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, ms));
    }

    /**
     * 应用请求拦截器
     */
    private async _applyRequestInterceptors(config: HttpRequestConfig): Promise<HttpRequestConfig> {
        let processedConfig = config;
        
        for (const interceptor of this._requestInterceptors) {
            if (interceptor.onFulfilled) {
                try {
                    processedConfig = await interceptor.onFulfilled(processedConfig);
                } catch (error) {
                    if (interceptor.onRejected) {
                        processedConfig = await interceptor.onRejected(error);
                    } else {
                        throw error;
                    }
                }
            }
        }
        
        return processedConfig;
    }

    /**
     * 应用响应拦截器
     */
    private async _applyResponseInterceptors<T>(response: HttpResponse<T>): Promise<HttpResponse<T>> {
        let processedResponse = response;
        
        for (const interceptor of this._responseInterceptors) {
            if (interceptor.onFulfilled) {
                try {
                    processedResponse = await interceptor.onFulfilled(processedResponse);
                } catch (error) {
                    if (interceptor.onRejected) {
                        throw await interceptor.onRejected(error);
                    } else {
                        throw error;
                    }
                }
            }
        }
        
        return processedResponse;
    }

    /**
     * 构建URL（处理GET参数）
     */
    private _buildUrl(url: string, params?: any): string {
        if (!params || typeof params !== 'object') {
            return url;
        }

        const queryString = Object.keys(params)
            .filter(key => params[key] !== undefined && params[key] !== null)
            .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
            .join('&');

        if (!queryString) {
            return url;
        }

        const separator = url.includes('?') ? '&' : '?';
        return `${url}${separator}${queryString}`;
    }

    /**
     * 准备请求数据
     */
    private _prepareRequestData(config: HttpRequestConfig): string | FormData | ArrayBuffer | null {
        if (!config.data) {
            return null;
        }

        if (config.method === HttpMethod.GET) {
            return null; // GET请求的数据已经在URL中
        }

        // 如果数据已经是字符串、FormData或ArrayBuffer，直接返回
        if (typeof config.data === 'string' || 
            config.data instanceof FormData || 
            config.data instanceof ArrayBuffer) {
            return config.data;
        }

        // JSON序列化
        try {
            return JSON.stringify(config.data);
        } catch (e) {
            throw new Error('请求数据序列化失败');
        }
    }

    /**
     * 解析响应头
     */
    private _parseHeaders(headerStr: string): Record<string, string> {
        const headers: Record<string, string> = {};
        
        if (!headerStr) {
            return headers;
        }

        headerStr.split('\r\n').forEach(line => {
            const parts = line.split(': ');
            if (parts.length === 2) {
                headers[parts[0].toLowerCase()] = parts[1];
            }
        });

        return headers;
    }

    /**
     * 创建错误对象
     */
    private _createError(message: string, config: HttpRequestConfig, status?: number, originalError?: any): HttpErrorResponse {
        return {
            message,
            status,
            config,
            originalError
        };
    }

    /**
     * 处理错误
     */
    private async _handleError(error: any, config: HttpRequestConfig): Promise<HttpErrorResponse> {
        // 应用响应拦截器的错误处理
        for (const interceptor of this._responseInterceptors) {
            if (interceptor.onRejected) {
                try {
                    return await interceptor.onRejected(error);
                } catch (e) {
                    error = e;
                }
            }
        }
        
        return error;
    }

    /**
     * 显示加载提示
     */
    private _showLoading(): void {
        this._pendingRequests++;
        if (this._pendingRequests === 1) {
            // 这里可以显示全局loading，比如调用UI管理器
            console.log('显示Loading...');
        }
    }

    /**
     * 隐藏加载提示
     */
    private _hideLoading(): void {
        this._pendingRequests = Math.max(0, this._pendingRequests - 1);
        if (this._pendingRequests === 0) {
            // 这里可以隐藏全局loading
            console.log('隐藏Loading...');
        }
    }
}

// 导出单例实例
export const httpMgr = HttpMgr.getInstance<HttpMgr>();